// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#include "mk_header.h"
#include "mk_aabb.h"
#include "mk_math.h"

namespace MK3DE
{
	void AABB::Merge(const D3DXVECTOR3* vec)
	{
		minPt.x = min(minPt.x, vec->x);
		minPt.y = min(minPt.y, vec->y);
		minPt.z = min(minPt.z, vec->z);
		maxPt.x = max(maxPt.x, vec->x);
		maxPt.y = max(maxPt.y, vec->y);
		maxPt.z = max(maxPt.z, vec->z);
	}

	void AABB::Merge(const AABB* aabb)
	{
		Merge(&aabb->maxPt);
		Merge(&aabb->minPt);
	}

	void AABB::Extract(D3DXVECTOR3 point[], int len)
	{
		len = min(len, 8);
		for (int i = 0; i < len; i++)
			point[i] = Point(i);
	}

	BOOL AABB::Intersect(float* hitDist, const D3DXVECTOR3* origPt, const D3DXVECTOR3* dir)
	{
		D3DXPLANE sides[6] = { 
			D3DXPLANE( 1, 0, 0, -minPt.x), D3DXPLANE(-1, 0, 0, maxPt.x),
			D3DXPLANE( 0, 1, 0, -minPt.y), D3DXPLANE(0, -1, 0, maxPt.y),
			D3DXPLANE( 0, 0, 1, -minPt.z), D3DXPLANE(0, 0, -1, maxPt.z) };

			*hitDist = 0.f;  // safe initial value
			D3DXVECTOR3 hitPt = *origPt;

			BOOL inside = FALSE;

			for (int i = 0; (i < 6) && !inside; i++)
			{
				float cosTheta = D3DXPlaneDotNormal(&sides[i], dir);
				float dist = D3DXPlaneDotCoord (&sides[i], origPt);

				//  if we're nearly intersecting, just punt and call it an intersection
				if (MK_ALMOST_ZERO(dist)) 
					return TRUE;

				//  skip nearly (&actually) parallel rays
				if (MK_ALMOST_ZERO(cosTheta)) 
					continue;

				//  only interested in intersections along the ray, not before it.
				*hitDist = -dist / cosTheta;
				if (*hitDist < 0.f)
					continue;

				hitPt = (*hitDist) * (*dir) + (*origPt);

				inside = TRUE;

				for (int j = 0; (j < 6) && inside; j++)
				{
					if (j == i)
						continue;

					float d = D3DXPlaneDotCoord(&sides[j], &hitPt);

					inside = ((d + 0.00015) >= 0.f) ? TRUE : FALSE;
				}
			}

			return inside;        
	}
}